package framework.sinkers;

import framework.Constants;
import framework.DataSink;

import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Hashtable;

/**
 *
 * Sink that writes data to a file
 */
public class FileSink extends DataSink {

    /**
     * The list of positions that the sink will care to write.
     */
    private int[] idsToPrint;

    /**
     * The class responsible for formatting the output to be written
     */
    private MeasureFormatter formatter;

    /**
     * The stream that will be writen to.
     */
    private BufferedOutputStream fileWritter;

    /**
     *
     * @param filePath The path of the output file.
     * @param idsToPrint The positions that the sink will care to write.
     * @param formatter The class responsible for generating the printed output.
     * @throws FileNotFoundException
     */
    public FileSink(String filePath, int[] idsToPrint, MeasureFormatter formatter) throws FileNotFoundException {
        this.formatter = formatter;
        this.idsToPrint = idsToPrint;

        this.fileWritter = new BufferedOutputStream(new FileOutputStream(filePath));
    }

    /**
     *
     * @param hash The set of pairs (ID, measurement) to be written
     * @throws IOException
     */
    @Override
    protected void write(Hashtable<Integer, Long> hash) throws IOException {

        long extrapolMask = 0;
        // get the extrapolated values mask
        Long measure = hash.remove(Constants.MASK_ID);
        if (measure != null) {
            extrapolMask = measure;
        }

        for (int id : this.idsToPrint) {
            measure = hash.get(id);
            if (measure != null) {

                // check if this is an extrapoled value (add * in the formatter for instance)
                boolean extrapol = (((extrapolMask >> id) & 1) == 1);

                this.fileWritter.write(String.format("%-" + 20 + "s", formatter.format(id, measure, extrapol)).getBytes());
            }
        }

        this.fileWritter.write("\r\n".getBytes());
    }

    /**
     * Closes the output stream.
     */
    @Override
    protected void finish() {
        try {
            this.fileWritter.close();
        } catch (IOException e) {
            System.out.println("\n" + this.getName() + "Error closing file handle.");
        }
    }

}
